package com.ybt.communicate.tcp.server;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

import com.ybt.communicate.core.IConnection;
import com.ybt.communicate.core.IProtocol;
import com.ybt.communicate.core.exception.ProtocolException;
import com.ybt.communicate.tcp.configration.TCPRuntimeConfig;
import com.ybt.communicate.tcp.dispacher.ITCPServerLongDispatcher;

public class TCPServerLong implements IProtocol {
    private static Logger logger = Logger.getLogger(TCPServerLong.class);
    private ServerSocket server;
    private ExecutorService executor;
    private ITCPServerLongDispatcher disptcher;
    private TCPRuntimeConfig config;
    private volatile boolean start;

    public boolean isStart() {
        // TODO Auto-generated method stub
        return start;
    }

    public TCPServerLong(TCPRuntimeConfig config) {
        this.config = config;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.wx.workflow.communicate.core.IRuntimeProtocol#start()
     */
    public void start() throws ProtocolException {
        // TODO Auto-generated method stub
        if (start) {
            // 服务器已经启动
            if (logger.isDebugEnabled()) {
                logger.debug("the server listening on port "
                        + +config.getPort() + " is already started");
            }
            return;
        }
        try {
            // 分发器
            disptcher = null;

            // 初始化分发线程池
            executor = Executors.newFixedThreadPool(config.getWorkThread());

            // 启动tcp服务器
            server = new ServerSocket();
            server.bind(new InetSocketAddress(config.getPort()));

            // 设置服务器状态：启动
            start = true;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new ProtocolException(e);
        }

        // 启动监听主线程
        new Thread() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (start) {
                    try {
                        // 接收客户端请求
                        final Socket client = server.accept();

                        // 分发客户端请求
                        executor.execute(new Runnable() {

                            public void run() {
                                // TODO Auto-generated method stub
                                while (start) {
                                    Object content = null;
                                    if (logger.isDebugEnabled()) {
                                        logger
                                                .debug("accept a new client socket from "
                                                        + client);
                                    }
                                    TCPServerLongConnection con = new TCPServerLongConnection(
                                            client, config);
                                    try {
                                        // 接收客户端数据
                                        content = con.receive();
                                    } catch (Exception e) {
                                        // 接收客户端数据出错，关闭socket
                                        try {
                                            if (logger.isDebugEnabled()) {
                                                logger
                                                        .debug("received data error, closeing socket from "
                                                                + client);
                                            }
                                            // 关闭连接
                                            client.close();
                                        } catch (Exception ex) {
                                            logger.error(
                                                    "an exception occurs while closeing the socket from "
                                                            + client, ex);
                                        }
                                        break;
                                    }
                                    // 分发请求
                                    try {
                                        disptcher.dispatch(content);
                                    } catch (Exception e) {
                                        logger.error(
                                                "an exception occurs while dispatching the request from "
                                                        + client, e);
                                    }
                                }
                            }
                        });
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        logger.error("accept the tcp client on port "
                                + config.getPort() + " failed", e);
                    }
                }
            }

        }.start();

        logger.debug("the tcp server is listening on port " + config.getPort()
                + ".....");
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.wx.workflow.communicate.core.IRuntimeProtocol#stop()
     */
    public void stop() throws ProtocolException {
        // TODO Auto-generated method stub
        if (!start) {
            // 服务器已经停止
            logger.debug("the server listening on port " + config.getPort()
                    + " is already stopped");
            return;
        }

        try {
            // 设置状态为关闭
            start = false;
            if (server != null) {
                // 关闭服务监听
                server.close();
            }
            if (executor != null) {
                // 关闭分发线程池
                executor.shutdown();
            }
            logger.debug("the tcp server listening on port " + config.getPort()
                    + " has stopped.....");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new ProtocolException(
                    "stop the tcp server listenning on port "
                            + config.getPort() + " failed", e);
        }
    }

    public IConnection createConnection() throws ProtocolException {
        // TODO Auto-generated method stub
        throw new ProtocolException("unsupport method for TCPServerShort");
    }

    public IConnection createConnection(long timeout) throws ProtocolException {
        // TODO Auto-generated method stub
        return createConnection();
    }

}
